/*
 * FileReader.c
 *
 *  Created on: Jan 24, 2012
 *      Author: Ivan Bannykh
 *      The file Reader section and then addition of others to it
 */

#include "FileReader.h"
#include "DecodedStructs.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <assert.h>


int main()
{

		/*gets a file name*/
		ILIST *list;
	int loop=1;

		while(loop==1)
		{
			/* doesnt take any name it needs an imput with  a .bin also doesnt check if a file exists before
			 * opening
			 * */
		char *s;
		s=malloc(3000*sizeof(char));
	    int length;
	    printf("Input File Name:");
	    scanf("%s", s);


	    /* insertion point for others code*/





		
	    length = strlen(s);
	    if(length<4)
	    {
	    	perror("Missing the extension:");
	    }
	    else
	    {
	    	FILE * file;

	    	if( (file = fopen(s, "r")) )
	    		{
	    			fclose(file);

	    			

	    			/*the extension so .exe or .bin the string for that a char[3] would be fine too
	    			 * mem leak eminent
	    			 *
	    			 */
	    			char *extension=malloc(1000*sizeof(char));
	    			char*output=malloc(1000*sizeof(char));
	    			/*sets the extension equal to the proper value*/
	    			strcat(extension,&s[length-3]);

	    			/*output is just the base name of the file*/


	    			strncpy( output, s, length-4);

	    			/*the hex file*/
	    			if(strncmp(extension,"hex",3)==0)
	    			{

	    				/*uses the object copy to create a bin file*/
	    				convertHex(output);

	    				/*reads the created bin file*/
	    				list= ReadBinFileIvanStyleInt(strcat(output,".bin"));
	    				loop=2;
	    				free(output);
	    						free(s);
	    						free(extension);

	    			}

	    			/*elf file*/
	    			else if(strncmp(extension,"elf",3)==0)
	    			{
	    				/* uses object copy to create an elf copy*/
	    				convertelf(output);
	    				convertHex(output);

	    				list= ReadBinFileIvanStyleInt(strcat(output,".bin"));
	    				loop=2;
	    				free(output);
	    						free(s);
	    						free(extension);

	   				}

	    			/*bin file*/
	    			else if(strncmp(extension,"bin",3)==0)
	    			{
	    				/*reads the inputed bin file*/
	    				list= ReadBinFileIvanStyleInt(s);
	    				loop=2;
	    				free(output);
	    						free(s);
	    						free(extension);
	    			}


	    	else
	      	 {
	    	   /*the input file was not found*/
	    	   perror("Invalid input extension not excepted (case matters)");
	    	   perror("Please input another file name extensions accepted .elf .hex. bin ");

	       }


	    			/*IF END*/
	    }
	    else
	    {
	      /*the input file was not found*/
	      perror("Invalid input File not found");
	     perror("Please input another file name");

	     }


	    	/*else end*/
	    }
	    /*while end*/
		}


	    /*dissasembler code section*/



		/*output of program*/


		/*freeing everything*/

		
		disassembler(list);
		format(list,"Checking.asci");
		DeleteInstructionList(list);
		return 0;
}

/*new list */
ILIST * NewInstructionList()
    {
       ILIST *l;
       l = malloc(sizeof(ILIST));
       if (! l)
       { perror("Out of memory! Aborting...");
           exit(10);
       } /* fi */
       l->Length = 0;
       l->First = NULL;
       l->Last = NULL;
       return l;
    }


/* delete a instruction list (and all entries) */
void DeleteInstructionList(ILIST *l)
{
   IENTRY *e, *n;
   assert(l);
   e = l->First;
   while(e)
   { n = e->Next;
       free(e);
       e = n;
   }
   free(l);
}


/* insert an instruction into a list */
void AppendInstruction(ILIST *l, unsigned int y)
{
   IENTRY *e = NULL;
   assert(l);
   e = malloc(sizeof(IENTRY));
   if (! e)
   { perror("Out of memory! Aborting...");
       exit(10);
   } /* fi */;

    e->instruction =y;
   if (l->Last)
   { e->List = l;
       e->Next = NULL;
       e->Prev = l->Last;
       l->Last->Next = e;
       l->Last = e;
   }
   else
   { e->List = l;
       e->Next = NULL;
       e->Prev = NULL;
       l->First = e;
       l->Last = e;
   }
   l->Length++;
}

/*this function takes the user inputted .elf file, then converts it to a binary file*/
void convertelf(char *x)
{
	/*stores the filename*/
		char *filename=malloc(3000*sizeof(char));
		strcpy(filename,x);
		/*filename Hex*/

		/*takes first string argument*/
		char *firstl;
		char *first=malloc(3000*sizeof(char));;
		firstl="objcopy  -I elf32-big ";
		strcpy(first,firstl);
		/*first objcopy -I ihex*/


		/*last part */
		char *last=malloc(3000*sizeof(char));
		char*lastl;
		lastl=" -j .text -O ihex ";
		strcpy(last,lastl);
		/*last -0 binary*/


		char *outputname=malloc(2000*sizeof(char));
		strcpy(outputname,filename);
		strcat(outputname,".hex");

		/*output name .bin*/

		char *inputname=malloc(2000*sizeof(char));
			strcpy(inputname,filename);
			strcat(inputname,".elf");
			/*input name */

		/*inputname hex.hex last -o binary first objcopy output name hex.bin*/

		strcat(first,inputname);
		strcat(first,last);
		strcat(first,outputname);


		system(first); /*calls the function on the command prompt, using the objcopy utility on the ladera server*/


	/*freeing allocated memory for the string*/ /* always returns this converted file name for the binary handling portion of the API*/
}


/*this function takes the user inputted .elf file, then converts it to a binary file*/
void convertHex(char *x)
{
	/*stores the filename*/
	char *filename=malloc(3000*sizeof(char));
	strcpy(filename,x);
	/*filename Hex*/

	/*takes first string argument*/
	char *firstl;
	char *first=malloc(3000*sizeof(char));;
	firstl="objcopy -I ihex ";
	strcpy(first,firstl);
	/*first objcopy -I ihex*/


	/*last part */
	char *last=malloc(3000*sizeof(char));
	char*lastl;
	lastl=" -O binary ";
	strcpy(last,lastl);
	/*last -0 binary*/


	char *outputname=malloc(2000*sizeof(char));
	strcpy(outputname,filename);
	strcat(outputname,".bin");

	/*output name .bin*/

	char *inputname=malloc(2000*sizeof(char));
		strcpy(inputname,filename);
		strcat(inputname,".hex");
		/*input name */

	/*inputname hex.hex last -o binary first objcopy output name hex.bin*/

	strcat(first,inputname);
	strcat(first,last);
	strcat(first,outputname);


	system(first); /*calls the function on the command prompt, using the objcopy utility on the ladera server*/


	/*freeing allocated memory for the string*/ /* always returns this converted file name for the binary handling portion of the API*/
}


/*prints out the Test_Instruction*/
void Test_Instruction(ILIST *h)
{	int x;
	/*loop to show ints*/
	IENTRY *g=h->First;
	/*not last value*/
	while(g->Next !=NULL)
	{
		x=g->instruction;
		printf("%u\n",x);
		g=g->Next;
	}
	/*last value*/
	printf("%u\n",h->Last->instruction);

}




/*used to read the ReadBinFileStyleInt*/
ILIST * ReadBinFileIvanStyleInt (char * fname)
{

	/*flips the numbers 36014621 when it should be 4621 3601*/

    FILE *fp;

    fp=fopen(fname, "rb");

    /*gets the file size*/

    fseek(fp, 0, SEEK_END); /* seek to end of file*/
    int size = ftell(fp); /*get current file pointer*/
    fseek(fp, 0, SEEK_SET);

    int i=0;


    ILIST * Instruction_List = NewInstructionList();

    /*read file*/
    if (fp)
    {
    	/*loop through the loop out of size*/
    	while(i<(size)/4)
   		{

    			unsigned int addition;

    			/*reads a single int from file 8 char*/
   				fread(&addition, sizeof(int), 1, fp);

   				/*gets the proper addition*/
   				addition=switchorder(addition);

   				/*adds the instruction to the list*/
    			AppendInstruction(Instruction_List,addition);

    			i++;
   		}

    }

    else
    {
    	perror("error. could not open file");
    	exit(10);
   }


   fclose(fp);


   /*Testing the function properly*/
   Test_Instruction(Instruction_List);

   return Instruction_List;

}

/* bitwise switching of the entire int*/
unsigned int switchorder(unsigned int x)
{
	unsigned int a,b,c,d,e,f,g,h,returnvalue;

	a=0;
	b=0;
	c=0;
	d=0;
	e=0;
	f=0;
	g=0;
	h=0;

	/*extracts the chars*/
	a=x&0xF0000000;
	b=x&0x0F000000;
	c=x&0x00F00000;
	d=x&0x000F0000;
	e=x&0x0000F000;
	f=x&0x00000F00;
	g=x&0x000000F0;
	h=x&0x0000000F;

	/*shifts them to the proper position*/
	a=a>>24;
	b=b>>24;
	c=c>>8;
	d=d>>8;
	e=e<<8;
	f=f<<8;
	g=g<<24;
	h=h<<24;

	/*combines the values*/
	returnvalue = a|b|c|d|e|f|g|h;


	return returnvalue;
}


/*main function and output team*/
/*Takes a linked list and creates a file using it.*/
